package tms.view;

import java.awt.Color;
import java.awt.GridLayout;
import java.util.List;

import javax.swing.JPanel;

import tms.controler.AddonController;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormSpecs;
import com.jgoodies.forms.layout.RowSpec;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.border.LineBorder;
import javax.swing.JComboBox;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.JSeparator;
import javax.swing.JButton;
import javax.swing.DefaultComboBoxModel;

@SuppressWarnings("rawtypes")
public class AddonView extends JPanel {

    private static final long serialVersionUID = 1L;

    private AddonController controller;
    private JCheckBox ckbPriority;
    private JComboBox cmbBaggage;
    private JComboBox cmbPayment;

    private SeatAssignmentPanel pnlDepartFlight;
    private SeatAssignmentPanel pnlReturnFlight;
    private JTabbedPane tabbedPane;
    private JButton btnContinue;

    public AddonView(AddonController controller) {
        this.controller = controller;
        initGUI();
    }

    @SuppressWarnings("unchecked")
    private void initGUI() {
        setLayout(new FormLayout(new ColumnSpec[] {
                FormSpecs.UNRELATED_GAP_COLSPEC,
                FormSpecs.DEFAULT_COLSPEC,
                FormSpecs.RELATED_GAP_COLSPEC,
                ColumnSpec.decode("default:grow"),
                FormSpecs.UNRELATED_GAP_COLSPEC},
            new RowSpec[] {
                FormSpecs.DEFAULT_ROWSPEC,
                FormSpecs.RELATED_GAP_ROWSPEC,
                FormSpecs.DEFAULT_ROWSPEC,
                FormSpecs.NARROW_LINE_GAP_ROWSPEC,
                FormSpecs.DEFAULT_ROWSPEC,
                FormSpecs.RELATED_GAP_ROWSPEC,
                RowSpec.decode("fill:max(220dlu;min)"),
                FormSpecs.PARAGRAPH_GAP_ROWSPEC,
                FormSpecs.DEFAULT_ROWSPEC,
                FormSpecs.NARROW_LINE_GAP_ROWSPEC,
                FormSpecs.DEFAULT_ROWSPEC,
                FormSpecs.RELATED_GAP_ROWSPEC,
                FormSpecs.DEFAULT_ROWSPEC,
                FormSpecs.PARAGRAPH_GAP_ROWSPEC,
                FormSpecs.DEFAULT_ROWSPEC}));

        JLabel lblSeatAssignment = new JLabel("Seat Assignment");
        add(lblSeatAssignment, "2, 3, 3, 1");

        JSeparator separator = new JSeparator();
        add(separator, "2, 5, 3, 1");

        tabbedPane = new JTabbedPane(JTabbedPane.TOP);
        add(tabbedPane, "2, 7, 3, 1, fill, fill");

        JLabel lblAdditionalServiceAnd = new JLabel("Additional Service and Items");
        add(lblAdditionalServiceAnd, "2, 9, 3, 1");

        add(new JSeparator(), "2, 11, 3, 1");

        JPanel pnlItems = new JPanel();
        pnlItems.setBorder(new EmptyBorder(0, 50, 0, 50));
        add(pnlItems, "2, 13, 3, 1, fill, fill");
        pnlItems.setLayout(new GridLayout(0, 5, 15, 0));

        ckbPriority = new JCheckBox("Priority");
        ckbPriority.setEnabled(false);
        pnlItems.add(ckbPriority);

        JLabel lblBaggage = new JLabel("Baggage:");
        lblBaggage.setHorizontalAlignment(SwingConstants.RIGHT);
        pnlItems.add(lblBaggage);

        cmbBaggage = new JComboBox();
        cmbBaggage.setEnabled(false);
        cmbBaggage.setModel(new DefaultComboBoxModel(new String[] {"< 10 kg", "10 - 30 kg", "> 30 kg"}));
        pnlItems.add(cmbBaggage);

        JLabel label = new JLabel("Payment:");
        label.setHorizontalAlignment(SwingConstants.RIGHT);
        pnlItems.add(label);

        cmbPayment = new JComboBox();
        cmbPayment.setEnabled(false);
        cmbPayment.setModel(new DefaultComboBoxModel(new String[] {"Pay later", "Pay via Card"}));
        pnlItems.add(cmbPayment);

        btnContinue = new JButton("Continue");
        btnContinue.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                controller.moveToConfirmView();
            }
        });
        add(btnContinue, "2, 15");
    }

    public void addSummaryView(SummaryPanel summaryView) {
        assert (summaryView != null);
        this.add(summaryView, "1, 1, 4, 1, fill, fill");
    }

    public void addDepartSeatAssignment(JPanel board) {
        pnlDepartFlight = new SeatAssignmentPanel(board);
        tabbedPane.addTab("Departure Flight", null, pnlDepartFlight, null);
    }

    public void addReturnSeatAssignment(JPanel board) {
        pnlReturnFlight = new SeatAssignmentPanel(board);
        tabbedPane.addTab("Return Flight", null, pnlReturnFlight, null);
    }

    public ActionListener getDepartCheckBoxListener() {
        ActionListener listener = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() instanceof SeatCheckBox) {
                    SeatCheckBox seat = (SeatCheckBox) e.getSource();
                    controller.setDepartSeatValue(seat.getSeatId());
                    System.out.println("<<< Seat: " + seat.getSeatId());
                }
            }
        };
        return listener;
    }

    public ActionListener getReturnCheckBoxListener() {
        ActionListener listener = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() instanceof SeatCheckBox) {
                    SeatCheckBox seat = (SeatCheckBox) e.getSource();
                    controller.setReturnSeatValue(seat.getSeatId());
                    System.out.println("<<< Seat: " + seat.getSeatId());
                }
            }
        };
        return listener;
    }

    /**
     * Populate a seat board as a panel
     * @param seatRow
     * @param seatCol
     * @param unavailableSeats
     * @param checkBoxListener
     * @return the board
     */
    public JPanel populateSeatBoard(int seatRow, int seatCol,
            List<Integer> unavailableSeats, ActionListener checkBoxListener) {

        assert (unavailableSeats != null);

        JPanel board = new JPanel();
        board.setLayout(new GridLayout(seatRow + 1, seatCol + 1, 6, 6));

        String[] columnHeader = new String[] {
                "", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"
        };

        JLabel label;
        // add columns header
        for (int i = 0; i < seatCol + 1; i++) {
            label = new JLabel("  " + columnHeader[i]);
            board.add(label);
        }
        SeatCheckBox ckbSeat;
        ButtonGroup group = new ButtonGroup();
        int currentSeat;
        for (int i = 0; i < seatRow; i++) {
            // add rows header
            label = new JLabel(String.valueOf(i + 1));
            board.add(label);
            for (int j = 0; j < seatCol; j++) {
                // currentRowIndex * numOfColumns + (currentColumnIndex + 1)
                currentSeat = i * seatCol + (j + 1);
                ckbSeat = new SeatCheckBox(currentSeat);
                ckbSeat.addActionListener(checkBoxListener);
                if (unavailableSeats.contains(currentSeat)) {
                    //unavailableSeats.remove(currentSeat);
                    ckbSeat.setEnabled(false);
                    ckbSeat.setSelected(true);
                } else {
                    group.add(ckbSeat);
                }
                board.add(ckbSeat);
            }
        }
        return board;
    }

    private class SeatCheckBox extends JCheckBox {

        private static final long serialVersionUID = 1L;

        /**
         *  Holds ID of a seat.
         *  Note: It should be starting from 1 to 90, 120...
         */
        private int seatId;

        public SeatCheckBox(int seatId) {
            super();
            this.seatId = seatId;
        }

        public int getSeatId() {
            return seatId;
        }
    }

    protected class SeatAssignmentPanel extends JPanel {

        private static final long serialVersionUID = 1L;
        private JPanel pnlSeatBoard;
        private JCheckBox ckbExitRow;
        private JCheckBox ckbUnavailabe;
        private JCheckBox ckbSelected;
        private JCheckBox ckbAvailable;

        public SeatAssignmentPanel(JPanel seatBoard) {
            FormLayout layout = new FormLayout(new ColumnSpec[] {
                    FormSpecs.DEFAULT_COLSPEC,
                    FormSpecs.RELATED_GAP_COLSPEC,
                    ColumnSpec.decode("max(150dlu;min)"),
                    FormSpecs.RELATED_GAP_COLSPEC,
                    ColumnSpec.decode("max(50dlu;default)"),
                    FormSpecs.RELATED_GAP_COLSPEC,
                    FormSpecs.DEFAULT_COLSPEC,
                    FormSpecs.RELATED_GAP_COLSPEC,
                    FormSpecs.DEFAULT_COLSPEC,
                    FormSpecs.RELATED_GAP_COLSPEC,
                    FormSpecs.DEFAULT_COLSPEC},
                new RowSpec[] {
                    FormSpecs.DEFAULT_ROWSPEC,
                    FormSpecs.RELATED_GAP_ROWSPEC,
                    FormSpecs.DEFAULT_ROWSPEC,
                    FormSpecs.RELATED_GAP_ROWSPEC,
                    FormSpecs.DEFAULT_ROWSPEC,
                    FormSpecs.RELATED_GAP_ROWSPEC,
                    FormSpecs.DEFAULT_ROWSPEC,
                    FormSpecs.RELATED_GAP_ROWSPEC,
                    RowSpec.decode("default:grow"),
                    FormSpecs.RELATED_GAP_ROWSPEC,
                    FormSpecs.DEFAULT_ROWSPEC});
            layout.setRowGroups(new int[][]{new int[]{5, 7, 9}});
            setLayout(layout);

            add(Tools.createLabel("Head"), "3, 3, center, default");

            add(Tools.createLabel("Legend"), "7, 3, 3, 1, center, default");

            pnlSeatBoard = new JPanel();
            pnlSeatBoard.setBorder(new LineBorder(new Color(0, 0, 0)));
            add(pnlSeatBoard, "3, 5, 1, 5, fill, fill");

            ckbAvailable = Tools.createCheckBox("Available");
            ckbAvailable.setEnabled(false);
            add(ckbAvailable, "7, 5");

            ckbSelected = Tools.createCheckBox("Selected");
            ckbSelected.setEnabled(false);
            add(ckbSelected, "9, 5");

            ckbUnavailabe = Tools.createCheckBox("Occupied/Unavailabe");
            ckbUnavailabe.setEnabled(false);
            add(ckbUnavailabe, "7, 7");

            ckbExitRow = Tools.createCheckBox("Exit Row");
            ckbExitRow.setEnabled(false);
            add(ckbExitRow, "9, 7");

            add(Tools.createLabel("Tail"), "3, 11, center, default");

            assert (seatBoard != null);
            pnlSeatBoard.add(seatBoard);
        }
    }
}
